﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

using Tradex.Messages;

namespace Tradex.ComponentModel {

    /// <summary>
    /// A Tradex dynamic object is an object representing a potentially dynamic view of an item. It is updated by consuming
    /// messages. A DynamicObject subclass has one or more properties that are themselves immutable classes - only the properties
    /// of a DynamicObject will ever change, not the properties of it's own properties.
    /// 
    /// DynamicObject subclasses show a dynamic view of the current status of the object they represent and allow databinding
    /// for updatable information in the stream of constantly changing state that is typical for a trading application.
    /// </summary>
    public abstract class DynamicObject : INotifyPropertyChanged {

        /// <summary>
        /// Empty Constructor
        /// </summary>
        protected DynamicObject() {
        }

        /// <summary>
        /// Constructor returning an action that can be used to feed messages into the Dynamicobject.
        /// </summary>
        /// <param name="inputAction"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021")]
        protected DynamicObject(out Action<Message> inputAction) {
            inputAction = new Action<Message> (ProcessMessage);
        }

        /// <summary>
        /// This placeholder is for the message handling routine which then allows the subclasses to
        /// implement their own updating mechanisms.
        /// </summary>
        /// <param name="message"></param>
        public abstract void ProcessMessage(Message message);

        /// <summary>
        /// The OnPropertyChanged method trows the PropertyChanged event handler if reasonable. This overload does not set
        /// or compare values, and should thus only be used to throw the PropertyChanged event for secondary / computed properties.
        /// </summary>
        /// <param name="property"></param>
        protected void OnPropertyChanged(string property) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        /// <summary>
        /// The OnPropetyChanged event handler. it is programmed in such a way to not throw an event if
        /// old and new value are identical, and otherwise be usable in only one code line.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045")]
        protected void OnPropertyChanged<T>(string property, ref T oldValue, T newValue) {
            if (!System.Object.Equals(oldValue, newValue)) {
                oldValue = newValue;
                OnPropertyChanged(property);
            }
            return;
        }

        /// <inheritdoc />
        public event PropertyChangedEventHandler PropertyChanged;

    }

}
